home *** CD-ROM | disk | FTP | other *** search
/ OpenGL Superbible (2nd Edition) / OpenGL SuperBible e2.iso / tools / GLUT-3.7 / PROGS / TIFF / writetiff.c < prev   
Encoding:
C/C++ Source or Header  |  1998-08-12  |  9.5 KB  |  331 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1997. */
  3.  
  4. /* This program is freely distributable without licensing fees  and is
  5.    provided without guarantee or warrantee expressed or  implied. This
  6.    program is -not- in the public domain. */
  7.  
  8. /* X compile line: cc -o writetiff writetiff.c -ltiff -lglut -lGLU -lGL -lXmu -lXext -lX11 -lm */
  9.  
  10. /* writetiff is a simple OpenGL program that writes out a TIFF file named
  11.    gears.tif containing an OpenGL-rendered scene containing 3 gears (the
  12.    gears rendering code is lifted from Brian Paul's gears.c Mesa demo.
  13.    writetiff uses Sam Leffler's libtiff library to write to a TIFF an image
  14.    grabbed from the screen with glReadPixels.  NOTE:  If the window is
  15.    obscured when the glReadPixels is performed, obscured pixels will be
  16.    undefined when written into the TIFF file. */
  17.  
  18. #include <stdlib.h>
  19. #include <math.h>
  20. #include <GL/glut.h>
  21. #include <tiffio.h>     /* Sam Leffler's libtiff library. */
  22.  
  23. /* Some <math.h> files do not define M_PI... */
  24. #ifndef M_PI
  25. #define M_PI 3.14159265358979323846
  26. #endif
  27.  
  28. static int W, H;
  29.  
  30. int
  31. writetiff(char *filename, char *description,
  32.   int x, int y, int width, int height, int compression)
  33. {
  34.   TIFF *file;
  35.   GLubyte *image, *p;
  36.   int i;
  37.  
  38.   file = TIFFOpen(filename, "w");
  39.   if (file == NULL) {
  40.     return 1;
  41.   }
  42.   image = (GLubyte *) malloc(width * height * sizeof(GLubyte) * 3);
  43.  
  44.   /* OpenGL's default 4 byte pack alignment would leave extra bytes at the
  45.      end of each image row so that each full row contained a number of bytes
  46.      divisible by 4.  Ie, an RGB row with 3 pixels and 8-bit componets would
  47.      be laid out like "RGBRGBRGBxxx" where the last three "xxx" bytes exist
  48.      just to pad the row out to 12 bytes (12 is divisible by 4). To make sure
  49.      the rows are packed as tight as possible (no row padding), set the pack
  50.      alignment to 1. */
  51.   glPixelStorei(GL_PACK_ALIGNMENT, 1);
  52.  
  53.   glReadPixels(x, y, width, height, GL_RGB, GL_UNSIGNED_BYTE, image);
  54.   TIFFSetField(file, TIFFTAG_IMAGEWIDTH, (uint32) width);
  55.   TIFFSetField(file, TIFFTAG_IMAGELENGTH, (uint32) height);
  56.   TIFFSetField(file, TIFFTAG_BITSPERSAMPLE, 8);
  57.   TIFFSetField(file, TIFFTAG_COMPRESSION, compression);
  58.   TIFFSetField(file, TIFFTAG_PHOTOMETRIC, PHOTOMETRIC_RGB);
  59.   TIFFSetField(file, TIFFTAG_SAMPLESPERPIXEL, 3);
  60.   TIFFSetField(file, TIFFTAG_PLANARCONFIG, PLANARCONFIG_CONTIG);
  61.   TIFFSetField(file, TIFFTAG_ROWSPERSTRIP, 1);
  62.   TIFFSetField(file, TIFFTAG_IMAGEDESCRIPTION, description);
  63.   p = image;
  64.   for (i = height - 1; i >= 0; i--) {
  65.     if (TIFFWriteScanline(file, p, i, 0) < 0) {
  66.       free(image);
  67.       TIFFClose(file);
  68.       return 1;
  69.     }
  70.     p += width * sizeof(GLubyte) * 3;
  71.   }
  72.   TIFFClose(file);
  73.   return 0;
  74. }
  75.  
  76. /**
  77.  
  78.   Draw a gear wheel.  You'll probably want to call this function when
  79.   building a display list since we do a lot of trig here.
  80.  
  81.   Input:  inner_radius - radius of hole at center
  82.           outer_radius - radius at center of teeth
  83.           width - width of gear
  84.           teeth - number of teeth
  85.           tooth_depth - depth of tooth
  86.  
  87.  **/
  88.  
  89. static void
  90. gear(GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
  91.   GLint teeth, GLfloat tooth_depth)
  92. {
  93.   GLint i;
  94.   GLfloat r0, r1, r2;
  95.   GLfloat angle, da;
  96.   GLfloat u, v, len;
  97.  
  98.   r0 = inner_radius;
  99.   r1 = outer_radius - tooth_depth / 2.0;
  100.   r2 = outer_radius + tooth_depth / 2.0;
  101.  
  102.   da = 2.0 * M_PI / teeth / 4.0;
  103.  
  104.   glShadeModel(GL_FLAT);
  105.  
  106.   glNormal3f(0.0, 0.0, 1.0);
  107.  
  108.   /* draw front face */
  109.   glBegin(GL_QUAD_STRIP);
  110.   for (i = 0; i <= teeth; i++) {
  111.     angle = i * 2.0 * M_PI / teeth;
  112.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  113.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  114.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  115.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  116.   }
  117.   glEnd();
  118.  
  119.   /* draw front sides of teeth */
  120.   glBegin(GL_QUADS);
  121.   da = 2.0 * M_PI / teeth / 4.0;
  122.   for (i = 0; i < teeth; i++) {
  123.     angle = i * 2.0 * M_PI / teeth;
  124.  
  125.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  126.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
  127.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
  128.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  129.   }
  130.   glEnd();
  131.  
  132.   glNormal3f(0.0, 0.0, -1.0);
  133.  
  134.   /* draw back face */
  135.   glBegin(GL_QUAD_STRIP);
  136.   for (i = 0; i <= teeth; i++) {
  137.     angle = i * 2.0 * M_PI / teeth;
  138.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  139.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  140.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  141.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  142.   }
  143.   glEnd();
  144.  
  145.   /* draw back sides of teeth */
  146.   glBegin(GL_QUADS);
  147.   da = 2.0 * M_PI / teeth / 4.0;
  148.   for (i = 0; i < teeth; i++) {
  149.     angle = i * 2.0 * M_PI / teeth;
  150.  
  151.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  152.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
  153.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
  154.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  155.   }
  156.   glEnd();
  157.  
  158.   /* draw outward faces of teeth */
  159.   glBegin(GL_QUAD_STRIP);
  160.   for (i = 0; i < teeth; i++) {
  161.     angle = i * 2.0 * M_PI / teeth;
  162.  
  163.     glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5);
  164.     glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5);
  165.     u = r2 * cos(angle + da) - r1 * cos(angle);
  166.     v = r2 * sin(angle + da) - r1 * sin(angle);
  167.     len = sqrt(u * u + v * v);
  168.     u /= len;
  169.     v /= len;
  170.     glNormal3f(v, -u, 0.0);
  171.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5);
  172.     glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5);
  173.     glNormal3f(cos(angle), sin(angle), 0.0);
  174.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5);
  175.     glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5);
  176.     u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
  177.     v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
  178.     glNormal3f(v, -u, 0.0);
  179.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5);
  180.     glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5);
  181.     glNormal3f(cos(angle), sin(angle), 0.0);
  182.   }
  183.  
  184.   glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5);
  185.   glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5);
  186.  
  187.   glEnd();
  188.  
  189.   glShadeModel(GL_SMOOTH);
  190.  
  191.   /* draw inside radius cylinder */
  192.   glBegin(GL_QUAD_STRIP);
  193.   for (i = 0; i <= teeth; i++) {
  194.     angle = i * 2.0 * M_PI / teeth;
  195.     glNormal3f(-cos(angle), -sin(angle), 0.0);
  196.     glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5);
  197.     glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5);
  198.   }
  199.   glEnd();
  200.  
  201. }
  202.  
  203. static GLfloat view_rotx = 20.0, view_roty = 30.0, view_rotz = 0.0;
  204. static GLint gear1, gear2, gear3;
  205. static GLfloat angle = 0.0;
  206.  
  207. static void
  208. draw(void)
  209. {
  210.   glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
  211.  
  212.   glPushMatrix();
  213.   glRotatef(view_rotx, 1.0, 0.0, 0.0);
  214.   glRotatef(view_roty, 0.0, 1.0, 0.0);
  215.   glRotatef(view_rotz, 0.0, 0.0, 1.0);
  216.  
  217.   glPushMatrix();
  218.   glTranslatef(-3.0, -2.0, 0.0);
  219.   glRotatef(angle, 0.0, 0.0, 1.0);
  220.   glCallList(gear1);
  221.   glPopMatrix();
  222.  
  223.   glPushMatrix();
  224.   glTranslatef(3.1, -2.0, 0.0);
  225.   glRotatef(-2.0 * angle - 9.0, 0.0, 0.0, 1.0);
  226.   glCallList(gear2);
  227.   glPopMatrix();
  228.  
  229.   glPushMatrix();
  230.   glTranslatef(-3.1, 4.2, 0.0);
  231.   glRotatef(-2.0 * angle - 25.0, 0.0, 0.0, 1.0);
  232.   glCallList(gear3);
  233.   glPopMatrix();
  234.  
  235.   glPopMatrix();
  236.  
  237.   glFlush();
  238. }
  239.  
  240. static void
  241. init(void)
  242. {
  243.   static GLfloat pos[4] =
  244.   {5.0, 5.0, 10.0, 0.0};
  245.   static GLfloat red[4] =
  246.   {0.8, 0.1, 0.0, 1.0};
  247.   static GLfloat green[4] =
  248.   {0.0, 0.8, 0.2, 1.0};
  249.   static GLfloat blue[4] =
  250.   {0.2, 0.2, 1.0, 1.0};
  251.  
  252.   glLightfv(GL_LIGHT0, GL_POSITION, pos);
  253.   glEnable(GL_CULL_FACE);
  254.   glEnable(GL_LIGHTING);
  255.   glEnable(GL_LIGHT0);
  256.   glEnable(GL_DEPTH_TEST);
  257.  
  258.   /* make the gears */
  259.   gear1 = glGenLists(1);
  260.   glNewList(gear1, GL_COMPILE);
  261.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, red);
  262.   gear(1.0, 4.0, 1.0, 20, 0.7);
  263.   glEndList();
  264.  
  265.   gear2 = glGenLists(1);
  266.   glNewList(gear2, GL_COMPILE);
  267.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, green);
  268.   gear(0.5, 2.0, 2.0, 10, 0.7);
  269.   glEndList();
  270.  
  271.   gear3 = glGenLists(1);
  272.   glNewList(gear3, GL_COMPILE);
  273.   glMaterialfv(GL_FRONT, GL_AMBIENT_AND_DIFFUSE, blue);
  274.   gear(1.3, 2.0, 0.5, 10, 0.7);
  275.   glEndList();
  276.  
  277.   glEnable(GL_NORMALIZE);
  278.  
  279.   glMatrixMode(GL_PROJECTION);
  280.   glLoadIdentity();
  281.   glFrustum(-1.0, 1.0, -1.0, 1.0, 5.0, 60.0);
  282.   glMatrixMode(GL_MODELVIEW);
  283.   glLoadIdentity();
  284.   glTranslatef(0.0, 0.0, -40.0);
  285. }
  286.  
  287. static void
  288. reshape(int width, int height)
  289. {
  290.   glViewport(0, 0, (GLint) width, (GLint) height);
  291.   W = width;
  292.   H = height;
  293. }
  294.  
  295. static void
  296. menu(int value)
  297. {
  298.   switch (value) {
  299.   case 1:
  300.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_LZW);
  301.     break;
  302.   case 2:
  303.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_NONE);
  304.     break;
  305.   case 3:
  306.     writetiff("gears.tif", "OpenGL-rendered gears", 0, 0, W, H, COMPRESSION_PACKBITS);
  307.     break;
  308.   }
  309. }
  310.  
  311. main(int argc, char *argv[])
  312. {
  313.   glutInit(&argc, argv);
  314.   glutInitDisplayMode(GLUT_RGB | GLUT_DEPTH);
  315.  
  316.   glutCreateWindow("writetiff");
  317.   init();
  318.  
  319.   glutDisplayFunc(draw);
  320.   glutReshapeFunc(reshape);
  321.  
  322.   glutCreateMenu(menu);
  323.   glutAddMenuEntry("Write gears.tiff (LZW compressed)", 1);
  324.   glutAddMenuEntry("Write gears.tiff (No compression)", 2);
  325.   glutAddMenuEntry("Write gears.tiff (Packbits)", 3);
  326.   glutAttachMenu(GLUT_RIGHT_BUTTON);
  327.  
  328.   glutMainLoop();
  329.   return 0;             /* ANSI C requires main to return int. */
  330. }
  331.